package com.lagou.edu.utils;

import java.io.*;

/**
 * 自定义类加载器，用于加载不同web应用中的类
 * <p>
 * 因为应用可以放在磁盘中的任意位置，不一定在当前应用中，所以不能直接用Class.forName加载
 *
 * @author liangzj
 * @date 2021/4/9 7:23
 */
public class MiniAppClassLoader extends ClassLoader {
    // 编译后.class文件的根路径
    private static final String CLASSES_PATH = File.separator + "target" + File.separator + "classes" + File.separator;
    // 应用的绝对路径
    private String appAbsolutePath;

    public MiniAppClassLoader(String appAbsolutePath) {
        this.appAbsolutePath = appAbsolutePath;
    }

    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        // 拼接.class文件的绝对路径，根据绝对路径将.class文件读入内存
        String aClassPath = name.replace(".", File.separator);
        String classAbsolutePath = appAbsolutePath + CLASSES_PATH + aClassPath + ".class";
        byte[] classBytes = readClassBytes(classAbsolutePath);

        if (classBytes == null || classBytes.length <= 0) {
            throw new ClassNotFoundException();
        }

        return defineClass(name, classBytes, 0, classBytes.length);
    }

    private byte[] readClassBytes(String path) {
        File file = new File(path);

        try (FileInputStream fis = new FileInputStream(file)) {

            ByteArrayOutputStream classBytesOutputStream = new ByteArrayOutputStream();
            byte[] buffBytes = new byte[1024];
            int readLength;
            while ((readLength = fis.read(buffBytes)) != -1) {
                classBytesOutputStream.write(buffBytes, 0, readLength);
            }

            return classBytesOutputStream.toByteArray();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return null;
    }

}
